package us.mooresr.geartrack.client.core.desktop;

import java.util.HashMap;
import java.util.List;

import us.mooresr.geartrack.client.core.presenter.ItemUiHandlers;
import us.mooresr.geartrack.shared.model.Item;
import us.mooresr.geartrack.shared.model.ItemType;
import us.mooresr.geartrack.shared.model.Location;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
import com.gwtplatform.mvp.client.Presenter;
import com.gwtplatform.mvp.client.ViewWithUiHandlers;

public class ItemForm extends Composite {

	@UiField TextBox nameBox;
	@UiField TextBox descriptionBox;
	@UiField TextBox serialBox;
	@UiField ListBox itemTypeListBox;
	@UiField ListBox locationListBox;

	private static ItemFormUiBinder uiBinder = GWT
			.create(ItemFormUiBinder.class);
	
	HashMap<Long, Integer> locationMap;
	HashMap<Integer, Long> locationReverseMap;
	HashMap<Long, Integer> itemTypeMap;
	HashMap<Integer, Long> itemTypeReverseMap;

	interface ItemFormUiBinder extends UiBinder<Widget, ItemForm> {
	}

	public ItemForm() {
		initWidget(uiBinder.createAndBindUi(this));
		
		locationMap = new HashMap<Long, Integer>();
		locationReverseMap = new HashMap<Integer, Long>();
		itemTypeMap = new HashMap<Long, Integer>();
		itemTypeReverseMap = new HashMap<Integer, Long>();
	}
	
	public String getName() {
		return nameBox.getText();
	}
	
	public String getDescription() {
		return descriptionBox.getText();
	}
	
	public String getSerial() {
		return serialBox.getText();
	}

	public Long getItemTypeId() {
		int index = itemTypeListBox.getSelectedIndex();
		
		if (index < 0) {
			return null;
		} else {
			return itemTypeReverseMap.get(index);
		}

	}
	
	public Long getLocationId() {
		int index = locationListBox.getSelectedIndex();
		
		if (index < 0) {
			return null;
		} else {
			return locationReverseMap.get(index);
		}
	}
	
	public void setName(String name) {
		nameBox.setValue(name);
	}
	
	public void setDescription(String description) {
		descriptionBox.setValue(description);
	}
	
	public void setSerial(Integer serial) {
		String serialString;
		
		if (serial == null) {
			serialString = "";
		} else {
			serialString = serial.toString();
		}
		serialBox.setValue(serialString);
	}
	
	public void setLocationId(Long locationId) {
		Integer index = locationMap.get(locationId);
		if (index == null) {
			locationListBox.setSelectedIndex(0);
		} else {
			locationListBox.setSelectedIndex(index);
		}
	}
	
	public void setItemTypeId(Long itemType) {
		Integer index = itemTypeMap.get(itemType);
		if (index == null) {
			itemTypeListBox.setSelectedIndex(0);
		} else {
			itemTypeListBox.setSelectedIndex(index);
		}
	}
	
	public void clear() {
		nameBox.setText("");
		descriptionBox.setText("");
		serialBox.setText("");
		
		int selectedIndex;
		selectedIndex = locationListBox.getSelectedIndex();
		if (selectedIndex != -1) {
			locationListBox.setItemSelected(selectedIndex,  false);
		}
	
		selectedIndex = itemTypeListBox.getSelectedIndex();
		if (selectedIndex != -1) {
			itemTypeListBox.setItemSelected(selectedIndex, false);
		}
	}
	
	public void setLocations(List<Location> locations) {
		locationListBox.clear();
		locationMap.clear();
		locationReverseMap.clear();
		Integer index = 0;
	
		locationListBox.addItem("<none>");
		locationMap.put(null,  index);
		locationReverseMap.put(index,  null);
		
		for (Location l : locations) {
			++index;
			locationListBox.insertItem(l.getName(), -1);
			locationMap.put(l.getId(),  index);
			locationReverseMap.put(index, l.getId());
		}
		
	}
	
	public void addLocation(Location location) {
		Integer index = locationListBox.getItemCount();
		
		locationListBox.insertItem(location.getName(), -1);
		locationMap.put(location.getId(),  index);
		locationReverseMap.put(index,  location.getId());
		
	}
	
	public void changeLocation(Location location) {
		Integer index = locationMap.get(location);
		locationListBox.setItemText(index,  location.getName());
		
	}
	
	public void removeLocation(Location location) {
		Integer index = locationMap.get(location);
		
		if (index == null) {
			// TODO: This shouldn't happen.  Perhaps we should be reporting this error?
			return;
		}
		
		locationListBox.removeItem(index);
		
		// When an item is removed the indexes of the remaining items change, so we need
		// to fix the maps
		
		// TODO:  There is almost certainly a more efficient way to do this
		
		// Remove any entry for the index we removed
		locationReverseMap.remove(index);
		locationMap.remove(location);
		
		// Any entry with an index > the one we removed needs to be decremented
		// First the forward map
		for (Long l : locationMap.keySet()) {
			if (locationMap.get(l) > index) {
				locationMap.put(l, index-1);
			}
		}
		
		// Then the reverse map
		for (Integer i : locationReverseMap.keySet()) {
			if (i > index) {
				Long value = locationReverseMap.get(i);
				locationReverseMap.remove(i);
				locationReverseMap.put(i,  value-1);
			}
		}
		
		
	}
	
	public void setItemTypes(List<ItemType> itemTypes) {
		itemTypeListBox.clear();
		itemTypeMap.clear();
		itemTypeReverseMap.clear();
		Integer index=0;
		
		itemTypeListBox.addItem("<none>");
		itemTypeMap.put(null,  index);
		itemTypeReverseMap.put(index,  null);
		
		for (ItemType i : itemTypes) {
			++index;
			itemTypeListBox.addItem(i.getName());
			itemTypeMap.put(i.getId(),  index);
			itemTypeReverseMap.put(index,  i.getId());
		}
		
	}
	
	public void addItemType(ItemType itemType) {
		Integer index = itemTypeListBox.getItemCount();
		
		itemTypeListBox.insertItem(itemType.getName(), -1);
		itemTypeMap.put(itemType.getId(),  index);
		itemTypeReverseMap.put(index,  itemType.getId());
		
	}
	
	public void changeItemType(ItemType itemType) {
		Integer index = itemTypeMap.get(itemType);
		
		itemTypeListBox.setItemText(index, itemType.getName());
		
	}
	
	public void removeItemType(ItemType itemType) {
		Integer index = itemTypeMap.get(itemType);
		
		itemTypeListBox.removeItem(index);
		
		// When an item is removed the indexes of the remaining items change, so we need
		// to fix the maps
		
		// TODO:  There is almost certainly a more efficient way to do this
		
		// Remove any entry for the index we removed
		itemTypeReverseMap.remove(index);
		itemTypeMap.remove(itemType);
		
		// Any entry with an index > the one we removed needs to be decremented
		// First the forward map
		for (Long l : itemTypeMap.keySet()) {
			if (itemTypeMap.get(l) > index) {
				itemTypeMap.put(l, index-1);
			}
		}
		
		// Then the reverse map
		for (Integer i : itemTypeReverseMap.keySet()) {
			if (i > index) {
				Long value = itemTypeReverseMap.get(i);
				itemTypeReverseMap.remove(i);
				itemTypeReverseMap.put(i,  value-1);
			}
		}
		
	}
	

}
